package com.wyg.lambda.example;

import com.wyg.lambda.entity.ExampleEntity;
import com.wyg.lambda.interfaces.IExample;
import com.wyg.lambda.interfaces.IExample2;

import java.util.concurrent.Callable;

/**
 * Lambda表达式-简单实例
 *
 *
 * 写好Lambda表达式注意事项：根据【函数式接口中的唯一抽象方法】，查看一下几点1参数，2返回值
 *
 * 第一步 先写好样式： () -> {}
 *
 *       1.1 （参数...） ->  {方法体...}
 *
 * 第二步 看有几个参数写入参数： (int a, int b ...) -> {}
 *
 *      2.1 有且仅有一个参数时，可以省略小括号()和参数类型，如 (int a) 简写成 a
 *      2.2 有多个参数时,都省略(或都不省略)参数类型,小括号必须存在：如 (int a,int b) 简写成(a,b)
 *
 * 第三步 看返回值，写方法体实现：  (int a, int b ...) -> { return a+b;};
 *
 *      3.1 有且仅有一句方法体时，可以省略大括号{};
 *              如：{Systemt.out.println("a");}; 简写成：Systemt.out.println("a");
 *              如：{return 123;} 简写成 return 123;
 *
 *      3.2 有且仅有一句方法体，并且有返回值时，可以省略大括号和return关键字;
 *              如：{return 123;} 简写成 123;
 *
 *      3.2 有多行方法体时，大括号{}必须存在，且方法体中的语句必须完整；
 *          如：{int a =12; return a;}
 *
 * @ClassName: Example_1
 * @Auther: WangYG
 * @Date: 2020-02-19 23:26:23
 * @Version: 1.0
 */
public class Example_1 {

    /**
     * 简单实例一：使用Runnable接口演示简单的Lambda表达式
     */
    public void simpleOne(){

        //普通的Runnable声明方式
        Runnable r1 = new Runnable() {
            @Override
            public void run() {
                System.out.println(" this is r1 function! ");
            }
        };
        r1.run();

        //lambda function - 唯一的抽象方法run() -> {方法体实现}
        Runnable r2 = () -> {System.out.println(" this is r2 function! ");};
        r2.run();

        //lambda function - 方法体只有一句时，可以省略大括号{}
        Runnable r3 = () -> System.out.println(" this is r3 function! ");
        r3.run();
    }

    /**
     * 功能描述: 简单示例二，使用Callable<?>接口演示使用Lambda表达式返回值示例
     * @methodName: simpleTwo
     * @params: []
     * @return: void
     * @exception:
     * @auther: WangYG
     * @date: 2020-02-20 00:44:11
     */
    public void simpleTwo() throws Exception {
        Callable<String> c1 = new Callable<String>() {
            @Override
            public String call() throws Exception {
                return "this is c1 call().";
            }
        };

        System.out.println(c1.call());

        //1.Lambda表达式 - 唯一的抽象方法call() -> {方法体返回值};
        //注意：Callable<String>接口中-call()方法是会抛出Exception异常的，但是Lambda表达式中是不会抛出异常的；
        //真正调用时在抛出异常！！！
        Callable<String> c2 = () -> {return "this is lambda c2 call().";};

        //调用时才会抛出Exception异常
        System.out.println(c2.call());

        //2.Lambda表达式 - 方法体只有一句时，1.可以省略大括号{}，2.可以省略return关键字;
        Callable<String> c3 = () -> "this is lambda c3 call().";
        System.out.println(c3.call());

    }

    /**
     * 功能描述:简单演示三：使用自定义接口IExample-演示有参数，无返回值的Lambda表达式写法。
     * @methodName: simpleThree
     * @params: []
     * @return: void
     * @exception:
     * @auther: WangYG
     * @date: 2020-02-20 01:04:09
     */
    public void simpleThree(){

        ExampleEntity entity1 = new ExampleEntity("普通方式",1000);
        ExampleEntity entity2 = new ExampleEntity("lambda表达式",2000);
        ExampleEntity entity3 = new ExampleEntity("lambda表达式-省略",3000);

        //1.普通方式使用
        IExample ie1 = new IExample() {
            @Override
            public void insert(ExampleEntity entity) {
                System.out.println(entity);
            }
        };

        ie1.insert(entity1);

        //2.使用Lambda表达式，唯一抽象方法 insert() -> {方法体实现}
        IExample ie2 = (ExampleEntity entity) -> {System.out.println(entity);};
        ie2.insert(entity2);

        //3.使用Lambda表达式-省略，
        //      1.有且仅有一个参数时-可以省略参数类型和小括号()，
        //      2.方法体中有且仅有一句语句时-可以省略大括号{};
        IExample ie3 = entity -> System.out.println(entity);
        ie3.insert(entity3);
    }

    /**
     * 功能描述: 简单演示三：使用自定义接口IExample2-演示有参数，有返回值的Lambda表达式写法。
     * @methodName: simpleFour
     * @params: []
     * @return: void
     * @exception:
     * @auther: WangYG
     * @date: 2020-02-20 01:18:01
     */
    public void simpleFour(){
        ExampleEntity entity1 = new ExampleEntity("普通方式",1000);
        ExampleEntity entity2 = new ExampleEntity("lambda表达式",2000);
        //多种省略方式，不止两种
        ExampleEntity entity3 = new ExampleEntity("lambda表达式-省略1参数部分",3000);
        ExampleEntity entity4 = new ExampleEntity("lambda表达式-省略2方法体部分",4000);

        //1.普通使用方式
        IExample2 ie = new IExample2() {
            @Override
            public ExampleEntity getEntity(ExampleEntity entity) {
                System.out.println("this is ：" + entity.getName());
                return entity;
            }
        };
        System.out.println(ie.getEntity(entity1));

        //2.lambda表达式：唯一抽象方法 getEntity() -> {方法体实现}
        IExample2 ie2 = (ExampleEntity entity) -> {
            System.out.println("this is ：" + entity.getName());
            return entity;
        };
        System.out.println(ie2.getEntity(entity2));

        //3.lambda表达式-省略 ：有且仅有一个参数时-可以省略参数类型和小括号()
        IExample2 ie3 = entity -> {
            System.out.println("this is ：" + entity.getName());
            return entity;
        };
        System.out.println(ie3.getEntity(entity3));

        //4.lambda表达式-省略 ：方法体中有且仅有一句语句时-1.可以省略大括号{},2可以省略return关键字;
        IExample2 ie4 = entity -> entity;
        System.out.println(ie4.getEntity(entity4));

    }

}
